#ifndef SKYROAD_CONNECTION_H_
#define SKYROAD_CONNECTION_H_


#include <list>
#include <string>
#include <ctime>

#include <boost/array.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/format.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/detail/atomic_count.hpp>

#include <boost/system/error_code.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio.hpp>



#include "reply.hpp"
#include "request.hpp"
#include "request_parser.hpp"

using namespace  boost;
using namespace  boost::asio;

class connection_manager;
class request_handler;

/// Represents a single connection from a client.
class connection : public boost::enable_shared_from_this<connection>, private boost::noncopyable
{
public:
    /// Construct a connection with the given io_service.
    explicit connection( asio::io_service&   io_service,
                         connection_manager& manager,
                         request_handler&    handler
                       );

    /// Get the connection id.
    unsigned int id();

    /// Get the socket associated with the connection.
    asio::ip::tcp::socket& socket();

    void async_write(const reply& r);

    asio::ip::tcp::endpoint remote_endpoint()
    {
        return m_socket.remote_endpoint();
    }


    bool timeout();

    bool reading()
    { 
        return m_reading;
    }

    /// Start the first asynchronous operation for the connection.
    void start();

    /// Stop all asynchronous operations associated with the connection.
    void stop();

    void shutdown();

private:


    void handle_bussion_branch();
    /// Handle completion of a read operation.
    void handle_read(const boost::system::error_code & e, std::size_t bytes_transferred);

    /// Handle completion of a write operation.
    void handle_write(const boost::system::error_code& e);

    /// Socket for the connection.
    asio::ip::tcp::socket m_socket;

    /// The manager for this connection.
    connection_manager& m_connection_manager;

    /// The handler used to process the incoming request.
    request_handler& m_request_handler;

    /// Buffer for incoming data.
    boost::array<char, 8192> m_buffer;

    /// The incoming request.
    request m_request;

    /// The parser for the incoming request.
    request_parser m_request_parser;

    /// The unique id for the connection.
    int m_id;

    std::list<reply> m_write_replies;

    std::time_t m_last_op_time;

    bool m_connected;

    bool m_active;

    bool m_reading;

    static boost::detail::atomic_count s_last_id;
};

typedef boost::shared_ptr<connection> connection_ptr;

#endif